package cn.summit.passwordsty.rsa;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.apache.commons.io.FileUtils;

/**
 * @author summit
 * @since 2021/8/15 13:33
 */
public class RSATest {

	public static void main(String[] args) throws Exception {
//		String pubFilePath = "a.pub";
//		String priFilePath = "a.pri";
		String algorithm = "RSA";
//		KeyGeneratorTool.generateKeyAsFile(pubFilePath, priFilePath, algorithm);

		String input = "hello word";
		PrivateKey privateKey = getPrivateKey("a.pri", algorithm);
		PublicKey publicKey = getPublicKey("a.pub", algorithm);
		String mw = encryptRSA(algorithm, publicKey, input);

		String output = deEncryptRSA(algorithm, privateKey, mw);

		System.err.println(output);
	}

	/**
	 * 返回私钥对象
	 */
	public static PrivateKey getPrivateKey(String priPath, String algorithm) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
		String priStr = FileUtils.readFileToString(new File(priPath), StandardCharsets.UTF_8.name());
		KeyFactory instance = KeyFactory.getInstance(algorithm);
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(priStr));
		return instance.generatePrivate(pkcs8EncodedKeySpec);
	}

	/**
	 * 返回公钥对象
	 */
	public static PublicKey getPublicKey(String pubPath, String algorithm) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
		String priStr = FileUtils.readFileToString(new File(pubPath), StandardCharsets.UTF_8.name());
		KeyFactory instance = KeyFactory.getInstance(algorithm);
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(priStr));
		return instance.generatePublic(x509EncodedKeySpec);
	}

	/**
	 * 加密
	 */
	private static String encryptRSA(String algorithm, Key key, String input) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
		Cipher cipher = Cipher.getInstance(algorithm);
		cipher.init(Cipher.ENCRYPT_MODE, key);
		byte[] bytes = cipher.doFinal(input.getBytes(StandardCharsets.UTF_8));
		return Base64.getEncoder().encodeToString(bytes);
	}

	/**
	 * 解密
	 */
	private static String deEncryptRSA(String algorithm, Key key, String input) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
		Cipher cipher = Cipher.getInstance(algorithm);
		cipher.init(Cipher.DECRYPT_MODE, key);
		byte[] decode = Base64.getDecoder().decode(input);
		byte[] bytes = cipher.doFinal(decode);
		return new String(bytes);
	}

}
